{-# LANGUAGE DeriveDataTypeable         #-}
{-# OPTIONS -Wall #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  DirectoryScript.Lib.FlatSyntax
-- Copyright   :  (c) Stephen Peter Tetley 2012
-- License     :  BSD3
--
-- Maintainer  :  stephen.tetley@gmail.com
-- Stability   :  experimental
-- Portability :  to be determined
--
-- /Flat/ syntax - no nesting.
--
-----------------------------------------------------------------------------


module DirectoryScript.Lib.FlatSyntax
  (
    Directory(..)
  , DirContent(..)
  , SubDir(..)
  , File(..)

  , invalid_date_time

  , dirChildren
  , dirSubDirs
  , dirFiles
  , dirDateTime
  , dirIsChild  

  ) where


import DirectoryScript.Lib.Base


import Data.List

import Data.Generics                    -- package: syb

-- | Directory containing sub-directories and files.
-- 
-- Sub-directories are not recursive.
-- 
-- All descendent sub-directories and files are listed, not just
-- those at the top-level.
-- 
data Directory = Directory
    { dir_path          :: FilePath
    , dir_content       :: [DirContent]
    }
  deriving (Eq,Ord,Show,Data,Typeable)

-- | Simple sum type of either sub-directory or file.
--
data DirContent = D SubDir
                | F File
  deriving (Eq,Ord,Show,Data,Typeable)

-- | Flat sub-directory - just path and file name.
--
data SubDir = SubDir 
     { sub_dir_path         :: FilePath
     , sub_dir_datetime     :: DateTime
     }
  deriving (Eq,Ord,Show,Data,Typeable)

data File = File 
     { file_path        :: FilePath
     , file_size        :: Integer
     , file_datetime    :: DateTime
     }
  deriving (Eq,Ord,Show,Data,Typeable)

dirChildren :: Directory -> [DirContent]
dirChildren (Directory _ xs) = filter notLink xs
  where
    notLink (D (SubDir name _)) = name /= "." && name /= ".."
    notLink (F {})              = True


dirSubDirs :: Directory -> [SubDir]
dirSubDirs (Directory _ xs) = foldr fn [] xs
  where
    fn (D (SubDir name dt)) ac 
        | name /= "." || name /= ".." = SubDir name dt: ac
    fn _                    ac        = ac

dirFiles :: Directory -> [File]
dirFiles (Directory _ xs) = foldr fn [] xs
  where
    fn (F file) ac = file : ac
    fn _        ac = ac


-- | aka time stamp of the directory \".\"
--
dirDateTime :: Directory -> DateTime
dirDateTime (Directory _ cs) = fn cs
  where 
    fn (D (SubDir name dt):_) | name == "." = dt
    fn (_:xs)                 = fn xs
    fn []                     = invalid_date_time


dirIsChild :: String -> Directory -> Bool
dirIsChild root dir = root `isPrefixOf` (dir_path dir)